/*
 * InDir3Block.cpp
 *
 *  Created on: Apr 19, 2011
 *      Author: Stefan
 */

#include "InDir3Block.h"
#include "FS.h"

InDir3Block::InDir3Block(int number, byte* data) : InDirBlock(number, data) {
	//amount = -1;
	/* amount is niet nodig (en anders moet het niet op deze manier berekend worden)
	 * -er kunnen nuladressen zijn met daarna niet-nul adressen (zie dumpfile)
	 * -hoeveel er gelezen kan worden kan afgeleid worden van de filesize in inode
	 * -er hoort nooit naar een adress buiten proportie te worden gevraagd
	 */
	for (int i = 0; i < 128; i++){ //indirectieblokken bevatten addressen van 4 bytes (zie dictaat bladzijde 91)
		layer[i] = readLong(i*4);
	}
}

InDir3Block::~InDir3Block() {
	delete layer;
}

void InDir3Block::addAddress(long address, int index){
	long indirblockaddress = layer[index/128];
	FS* fs = FS::getInstance();
	if(indirblockaddress == 0){
		byte newData[DSKBLKSIZ];
		for(int i = 0; i < DSKBLKSIZ; i++){
			newData[i] = 0;
		}
		indirblockaddress = fs->getSuperBlock()->getFreeBlockAddress();
		layer[index/128] = indirblockaddress;
		write(index/128, layer[index/128]);
		fs->writeBlock(indirblockaddress, newData, DSKBLKSIZ);
	}
	InDir2Block* inDir2Block = new InDir2Block(indirblockaddress, fs->readBlock(indirblockaddress));
	inDir2Block->addAddress(address, index%128);
}

long InDir3Block::getAddress(int index){
	long indirblockaddress = layer[index/128];
	if(indirblockaddress == 0){//lege data
		return 0;
	}
	FS* fs = FS::getInstance();
	InDir2Block* inDir2Block = new InDir2Block(indirblockaddress, fs->readBlock(indirblockaddress));
	return inDir2Block->getAddress(index%128);
}

void InDir3Block::removeAddress(int index){
	long indirblockaddress = layer[index/128];
	InDir2Block* inDir2Block = new InDir2Block(indirblockaddress, FS::getInstance()->readBlock(indirblockaddress));
	inDir2Block->removeAddress(index%128);
}

void InDir3Block::print(){
	FS* fs = FS::getInstance();
	for(int i = 0; i < 128; i++){
		cout << " [[" << layer[i] << "]]";
		if(layer[i] > 0){
			InDir2Block* indir = new InDir2Block(layer[i], fs->readBlock(layer[i]));
			indir->print();
		}
	}
}

void InDir3Block::free(){
	FS* fs = FS::getInstance();
	for(int i = 0; i < 128; i++){
		if(layer[i] != 0){
			InDir2Block* indir = new InDir2Block(layer[i], fs->readBlock(layer[i]));
			indir->free();
			fs->addFreeBlock(layer[i]);
		}
	}
}
